#include "widget.h"
#include "ui_widget.h"
#include <QLCDNumber>
#include <thread>
//QLCDNumber控件示例-倒计时示例
/* 这个倒计时的示例
 * 需要用到一个定时器，即每隔固定时间触发一个指定的信号
 * C++标准库中，没有提供这个定时器，Boost库中实现了
 * Qt中也封装了对应的定时器 - QTimer类
 * QTimer类
 * 通过这个类创建出来的对象，就会每隔一定时间(用户自己设置)产生一个timeout这样的信号
 * 用户可以通过start()这个接口启动这个定时器，并在参数中设置触发timeout信号的周期时间
 * 结合connect，将timeout信号绑定到需要的槽函数中，就可以执行逻辑，修改LCDNumber中的数字了
 *
 * 原理：通过QTimer类对象，设置指定周期触发timeout信号，设置timeout信号触发时的槽函数
 * 在槽函数中执行对LCDNumber控件上显示数字信息的更新，从而达到倒计时的效果。
 *
*/
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建显示控件
    lcdnumber=new QLCDNumber(this);
    //设置显示控件的大小和尺寸
    lcdnumber->setGeometry(250,200,300,100);
    //设置初始值
    lcdnumber->display(10);

    //构造周期性触发timeout信号控件
    timer=new QTimer(this);
    //启动 并 设置触发timeout信号的周期  单位：毫秒
    timer->start(1000);
    //设置信号和槽函数  触发timeout信号时，执行handler槽函数
    connect(timer,&QTimer::timeout,this,&Widget::handler);

//    std::thread t([this](){
//        int value=lcdnumber->intValue();
//        while(true)
//        {
//            //休眠1秒
//            std::this_thread::sleep_for(std::chrono::seconds(1));
//            if(value<=0)
//            {
//                break;
//            }
//            value-=1;
//            lcdnumber->display(value);
//        }
//    });
    /* 如果这样实现倒计时，就会存在一些问题
     * 设置循环，每隔1秒，就更新一次显示控件上的信息即可
     *
     * Sleep这个睡眠函数，是windows API 需要包含Windows.h 头文件才可以使用
     * C++11中也引入了sleep_for操作，作用和sleep一样
     * 只是需要先拿到主线程this_thread::sleep_for(chrono::Seconds(休眠秒数))
     *
     * 在构造函数中，另外创建一个线程，在新的线程中，执行循环+更新的操作即可
     * 线程操作本身就是操作系统提供的api
     * 标准库就可以通过一些 条件编译 的方式来兼容不同的系统
     * 在Qt中，里面有一个专门的线程去负责维护更新(主线程)窗口界面
     * 对于GUI来说，内部包含了很多隐藏的状态，Qt为了保证修改界面的过程中，线程安全是不会受到影响的，Qt禁止了其他线程直接修改界面
     * 所以，Qt为了确保线程安全，直接要求所有的对界面的修改操作，必须在主线程中完成，所以，对于Qt槽函数来说，默认情况下
     * 槽函数都是由主线程去调用的，在槽函数中修改界面是没有任何问题的
     * a.exec()就会使得主线程进入 事件循环
     * exec就会一直循环下去，每执行一次循环，就会有一些固定的事情要处理，例如：更新当前页面...
     *
     * 所以：更新当前页面的操作需要在主线程中去完成
    */
}

Widget::~Widget()
{
    delete ui;
}

void Widget::handler()
{
    //获取LCDNumber控件中的数字
    int value = lcdnumber->intValue();
    if(value<=0)
    {
        //如果显示的数字<=0时，则停止周期性触发timeout信号即可
        timer->stop();
        return;
    }
    //数字>0
    //重新设置显示控件中的数字
    lcdnumber->display(value-1);

}



